package cn.comon.app.scan.controller;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.comon.app.scan.component.SysConfigBean;
import cn.comon.app.scan.entity.AsEnterpriseip;
import cn.comon.app.scan.entity.AsRequest;
import cn.comon.app.scan.service.AsRequestService;
import cn.comon.app.scan.service.AsEnterpriseipService;
import cn.comon.app.scan.util.AppstoreDuplClear;
import cn.comon.app.scan.util.SpringContextUtil;
import cn.comon.app.scan.util.UtilTools;

/**APP商店举报信息接入接口
 * @author xujf
 */
@Controller
@RequestMapping("/")
public class AppStoreController {
    @Autowired
    private AsEnterpriseipService asEnterpriseipService;
    @Autowired
    private AsRequestService asRequestService;
    private SysConfigBean sysConfigBean = (SysConfigBean)SpringContextUtil.getBean("sysConfigBean");
    private static Logger logger = Logger.getLogger(AppStoreController.class.getName());
    /**
     * 缓存容器
     */
    private Map<String, Integer> cacheMap = new ConcurrentHashMap<String, Integer>();

    public AppStoreController() {
        //每个300000（5分钟）线程启动一次，判断map里的时间是否超过5分钟，超过的就清除
        //单位毫秒
        int time = Integer.parseInt(SysConfigBean.getProperty("app.remove.time"));
        //单位秒
        int removeTime = Integer.parseInt(SysConfigBean.getProperty("app.remove.maxtime"));
        AppstoreDuplClear app = new AppstoreDuplClear(cacheMap, time*1000, removeTime);
        Thread appThread = new Thread(app, "举报信息是否有效判断的缓存定时删除线程");
        appThread.start();
    }
    
    /**
     * APP商店数据接入接口
     * @return 返回应答信息
     */
    @RequestMapping(value = "report", produces="text/html;charset=UTF-8")
    @ResponseBody //可将返回的内容直接输出，或者直接显示在页面
    public String report(ModelMap map, HttpServletRequest request) {
        JSONObject result = new JSONObject();
        try {
            //获取APP商店请求信息
            //Post方式，传递没有参数名的参数的获取方法是：
            //1）、如果对方是用下面的方式提交的：
            //uc.setRequestProperty("content-type", "text/html");
            //那么，可以用数据流的方式
            String value = null;
            InputStream in = request.getInputStream();
            int len=0;
            byte[] buffer = new byte[1024];
            while((len = in.read(buffer)) > 0){
                value = new String(buffer,0,len);
            }

            // 2）、如果对方是用下面的方式提交的：
            //uc.setRequestProperty("content-type","application/x-ww w-form-urlencoded")
            //那么，就不能用数据流的方式，因为会接不到流，那么可以使用
            if (value == null) {
                Map<String, String> mapTmp = request.getParameterMap();
                Iterator<String>  iter = (Iterator<String> ) mapTmp.keySet().iterator();
                while (iter.hasNext()) {
                    value = iter.next().toString();
                }
            }
            logger.info("thi value of interface from APPStroe =" + value);
            //APP商店数据解析
            String account = null;
            String packageurl = null;
            String packagename = null;
            String packagetype = null;
            String appchannel = null;
            String orig = null;
            String clientip = null;
            String descr = null;
            String reporttime = null;
            if (value != null) {
                value = URLDecoder.decode(value, "UTF-8");
                logger.info("the value of interface from APPStroe =" + value);

                JSONObject jsonObj = JSONObject.fromObject(value);
                if (jsonObj.containsKey("account")) {
                    account = jsonObj.getString("account");
                }
                if (jsonObj.containsKey("packageurl")) {
                    packageurl = jsonObj.getString("packageurl");
                }
                if (jsonObj.containsKey("packagename")) {
                    packagename = jsonObj.getString("packagename");
                }
                packagetype = jsonObj.getString("packagetype");
                if (jsonObj.containsKey("appchannel")) {
                    appchannel = jsonObj.getString("appchannel");
                }
                if (jsonObj.containsKey("orig")) {
                    orig = jsonObj.getString("orig");
                }
                if (jsonObj.containsKey("clientip")) {
                    clientip = jsonObj.getString("clientip");
                }
                if (jsonObj.containsKey("descr")) {
                    descr = jsonObj.getString("descr");
                }
                if (jsonObj.containsKey("reporttime")) {
                    reporttime = jsonObj.getString("reporttime");
                }

                //参数check
                if (account == null || account.trim().equals("")) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if (packageurl == null || packageurl.trim().equals("") ||  packageurl.getBytes().length > 2048) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((packagename != null && !packagename.trim().equals("")) && packagename.getBytes().length > 200) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if (packagetype == null || packagetype.trim().equals("") || (!"1".equals(packagetype) && !"2".equals(packagetype)
                        && !"3".equals(packagetype) && !"4".equals(packagetype) && !"5".equals(packagetype)
                        && !"6".equals(packagetype) && !"7".equals(packagetype) && !"8".equals(packagetype)
                        && !"9".equals(packagetype))) {
                    //1：android安装包 2：sis格式安装包 3：sisx格式安装包 4：jar格式安装包 5： dep 6：ipa 7：jad 8：wgz 9：wgt
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((appchannel != null && !appchannel.trim().equals("")) && appchannel.getBytes().length > 50) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((orig != null && !orig.trim().equals("")) && (!"1".equals(orig)
                        && !"2".equals(orig) && !"3".equals(orig))) { //1：PC客户端 2：PC端网页 3：移动 
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((clientip != null && !clientip.trim().equals("")) && clientip.getBytes().length > 15) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((descr != null && !descr.trim().equals("")) && descr.getBytes().length > 200) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((reporttime != null && !reporttime.trim().equals("")) && UtilTools.getTimestamp(reporttime) == null) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                }
            } else {
                result.put("result", "106");
                result.put("descr", "没有提交数据");
            }
            if (result.containsKey("result")) {
                return result.toString();
            }
            //请求ip是否合法
            String peerip = UtilTools.getIpAddr(request);
            //检测
            AsEnterpriseip asEnterpriseip = new AsEnterpriseip();
            asEnterpriseip.setEip_num(peerip);
            asEnterpriseip.setEi_num(account);
            asEnterpriseip.setStatus(1);
            if (asEnterpriseipService.getUserByIPCcount(asEnterpriseip) == null) {
                result.put("result", "108");
                result.put("descr", "不允许操作/认证失败（可能是请求IP和帐号不匹配）");
                return result.toString();
            }
            AsRequest asRequest = new AsRequest();
            asRequest.setPackageUrl(packageurl);
            asRequest.setPackageUrlHash(UtilTools.getStringMd5(packageurl));
            asRequest.setPackageName(packagename);
            asRequest.setPackageType(packagetype);
            asRequest.setAppChannel(appchannel);
            //TODO 是否为有效举报{0:有效,1:无效}缓存：memcached技术
            //TODO 根据举报的url和clientip参数， 如果一定时间内相同则判断为重复举报（原接口是5分钟以内重复算无效）
            //TODO dup
            //TODO 这个占很少内存,内存中就放一个url+clientip
            synchronized (this) {
                String urlAndClientIP = packageurl.trim() + clientip.trim();
                if (cacheMap.containsKey(urlAndClientIP)) {
                    //"app.report.time"时间以内，相同的ip和url的举报信息又被发送过来，视为无效举报信息
                    if (UtilTools.getTimestamp(0) - cacheMap.get(urlAndClientIP) <= 60 * Integer.parseInt(SysConfigBean.getProperty("app.report.time").trim())) {
                        asRequest.setDup(1);
                    } else {
                        asRequest.setDup(0);
                        cacheMap.put(urlAndClientIP, UtilTools.getTimestamp(0));
                    }
                } else {
                    asRequest.setDup(0);
                    cacheMap.put(urlAndClientIP, UtilTools.getTimestamp(0));
                }
            }
            asRequest.setDescr(descr);
            asRequest.setAccount(account);
            if (orig == null || orig.trim().equals("")) {
                asRequest.setOrig(-1);
            } else {
                asRequest.setOrig(Integer.parseInt(orig));
            }
            asRequest.setClient_ip(clientip);
            asRequest.setPeerip(peerip);
            asRequest.setCreateTime(UtilTools.getTimestamp(0));
            //该款APP被举报的时间
            asRequest.setReportTime(Integer.parseInt(reporttime));
            //APPStroe的数据验证完毕，更新DB
            synchronized (this) {
                asRequestService.addObj(asRequest);
            }
            //DB更新成功。
            result.put("result", "0");
            result.put("descr", "成功");
        } catch (JSONException e) {
            logger.error(e.getMessage());
            result.put("result", "102");
            result.put("descr", "格式错误");
        }  catch (NoSuchElementException e) {
            logger.error(e.getMessage());
            result.put("result", "105");
            result.put("descr", "参数错误");
        } catch (Exception e) {
            logger.error(e.getMessage());
            result.put("result", "101");
            result.put("descr", "发生未知异常");
        } finally {
            try {
                map.put("result", URLEncoder.encode(result.toString(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                logger.error(e.getMessage());
            }
            logger.info("result=" + result.toString());
        }
        return result.toString();
    }
    
    /**
     * APP商店数据接入接口(测试用)
     * @return 返回应答信息(不更新数据库)
     */
    @RequestMapping(value = "report.api/test", produces="text/html;charset=UTF-8")
    @ResponseBody //可将返回的内容直接输出，或者直接显示在页面
    public String reportTest(ModelMap map, HttpServletRequest request) {
        JSONObject result = new JSONObject();
        try {
            //获取APP商店请求信息
            //Post方式，传递没有参数名的参数的获取方法是：
            //1）、如果对方是用下面的方式提交的：
            //uc.setRequestProperty("content-type", "text/html");
            //那么，可以用数据流的方式
            String value = null;
            InputStream in = request.getInputStream();
            int len=0;
            byte[] buffer = new byte[1024];
            while((len = in.read(buffer)) > 0){
                value = new String(buffer,0,len);
            }

            // 2）、如果对方是用下面的方式提交的：
            //uc.setRequestProperty("content-type","application/x-ww w-form-urlencoded")
            //那么，就不能用数据流的方式，因为会接不到流，那么可以使用
            if (value == null) {
                Map<String, String> mapTmp = request.getParameterMap();
                Iterator<String>  iter = (Iterator<String> ) mapTmp.keySet().iterator();
                while (iter.hasNext()) {
                    value = iter.next().toString();
                }
            }
            logger.info("thi value of interface from APPStroe =" + value);
            //APP商店数据解析
            String account = null;
            String packageurl = null;
            String packagename = null;
            String packagetype = null;
            String appchannel = null;
            String orig = null;
            String clientip = null;
            String descr = null;
            String reporttime = null;
            if (value != null) {
                value = URLDecoder.decode(value, "UTF-8");
                logger.info("the value of interface from APPStroe =" + value);

                JSONObject jsonObj = JSONObject.fromObject(value);
                if (jsonObj.containsKey("account")) {
                    account = jsonObj.getString("account");
                }
                if (jsonObj.containsKey("packageurl")) {
                    packageurl = jsonObj.getString("packageurl");
                }
                if (jsonObj.containsKey("packagename")) {
                    packagename = jsonObj.getString("packagename");
                }
                packagetype = jsonObj.getString("packagetype");
                if (jsonObj.containsKey("appchannel")) {
                    appchannel = jsonObj.getString("appchannel");
                }
                if (jsonObj.containsKey("orig")) {
                    orig = jsonObj.getString("orig");
                }
                if (jsonObj.containsKey("clientip")) {
                    clientip = jsonObj.getString("clientip");
                }
                if (jsonObj.containsKey("descr")) {
                    descr = jsonObj.getString("descr");
                }
                if (jsonObj.containsKey("reporttime")) {
                    reporttime = jsonObj.getString("reporttime");
                }

                //参数check
                if (account == null || account.trim().equals("")) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if (packageurl == null || packageurl.trim().equals("") ||  packageurl.getBytes().length > 2048) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((packagename != null && !packagename.trim().equals("")) && packagename.getBytes().length > 200) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if (packagetype == null || packagetype.trim().equals("") || (!"1".equals(packagetype) && !"2".equals(packagetype)
                        && !"3".equals(packagetype) && !"4".equals(packagetype) && !"5".equals(packagetype)
                        && !"6".equals(packagetype) && !"7".equals(packagetype) && !"8".equals(packagetype)
                        && !"9".equals(packagetype))) {
                    //1：android安装包 2：sis格式安装包 3：sisx格式安装包 4：jar格式安装包 5： dep 6：ipa 7：jad 8：wgz 9：wgt
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((appchannel != null && !appchannel.trim().equals("")) && appchannel.getBytes().length > 50) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((orig != null && !orig.trim().equals("")) && (!"1".equals(orig)
                        && !"2".equals(orig) && !"3".equals(orig))) { //1：PC客户端 2：PC端网页 3：移动 
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((clientip != null && !clientip.trim().equals("")) && clientip.getBytes().length > 15) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((descr != null && !descr.trim().equals("")) && descr.getBytes().length > 200) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                } else if ((reporttime != null && !reporttime.trim().equals("")) && UtilTools.getTimestamp(reporttime) == null) {
                    result.put("result", "105");
                    result.put("descr", "参数错误");
                }
            } else {
                result.put("result", "106");
                result.put("descr", "没有提交数据");
            }
            if (result.containsKey("result")) {
                return result.toString();
            }
            //请求ip是否合法
            String peerip = UtilTools.getIpAddr(request);
            //检测
            AsEnterpriseip asEnterpriseip = new AsEnterpriseip();
            asEnterpriseip.setEip_num(peerip);
            asEnterpriseip.setEi_num(account);
            asEnterpriseip.setStatus(1);
            if (asEnterpriseipService.getUserByIPCcount(asEnterpriseip) == null) {
                result.put("result", "108");
                result.put("descr", "不允许操作/认证失败（可能是请求IP和帐号不匹配）");
                return result.toString();
            }
            //数据校验成功，测试通过。
            //DB更新成功。（测试地址不需要更新数据库）
            result.put("result", "0");
            result.put("descr", "成功");
        } catch (JSONException e) {
            logger.error(e.getMessage());
            result.put("result", "102");
            result.put("descr", "格式错误");
        }  catch (NoSuchElementException e) {
            logger.error(e.getMessage());
            result.put("result", "105");
            result.put("descr", "参数错误");
        } catch (Exception e) {
            logger.error(e.getMessage());
            result.put("result", "101");
            result.put("descr", "发生未知异常");
        } finally {
            try {
                map.put("result", URLEncoder.encode(result.toString(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                logger.error(e.getMessage());
            }
            logger.info("result=" + result.toString());
        }
        return result.toString();
    }
}